﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.Windows.Controls.Primitives;
using System.Collections.ObjectModel;
using System.ComponentModel;

namespace New3DDemo
{
    /// <summary>
    /// Lane.xaml 的交互逻辑
    /// </summary>
    public partial class Lane : Canvas
    {

        #region 构造

        public Lane()
        {    
            InitializeComponent();
            this.DataContext = this;
        } 

        #endregion

        #region 依赖属性

        #region OriginPoints

        public PointCollection OriginPoints
        {
            get { return (PointCollection)GetValue(OriginPointsProperty); }
            set { SetValue(OriginPointsProperty, value); }
        }

        // Using a DependencyProperty as the backing store for OriginPoints.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty OriginPointsProperty =
            DependencyProperty.Register("OriginPoints", typeof(PointCollection), typeof(Lane), new UIPropertyMetadata(new PropertyChangedCallback(PropertyChanged)));

        private static void PropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            ((Lane)d).CalMiddleLinePoints();
        }
        #endregion

        #region MiddleLinePoints

        /// <summary>
        ///构成 Lane中分线的点集合
        /// </summary>
        public PointCollection MiddleLinePoints
        {
            get { return (PointCollection)GetValue(PointsListProperty); }
            set { SetValue(PointsListProperty, value); }
        }

        // Using a DependencyProperty as the backing store for PointsList.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty PointsListProperty =
            DependencyProperty.Register("MiddleLinePoints", typeof(PointCollection), typeof(Lane), new UIPropertyMetadata(new PointCollection(), new PropertyChangedCallback(MiddleLinePointsPropertyChanged)));

        private static void MiddleLinePointsPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            ((Lane)d).PointsList_CollectionChanged();
        }
        
        #endregion        
        
        #region LaneWidth

        /// <summary>
        /// 车道宽度
        /// </summary>
        public double LaneWidth
        {
            get { return (double)GetValue(LaneWidthProperty); }
            set { SetValue(LaneWidthProperty, value); }
        }

        public static readonly DependencyProperty LaneWidthProperty =
            DependencyProperty.Register("LaneWidth", typeof(double), typeof(Lane), new UIPropertyMetadata(20.0, new PropertyChangedCallback(PropertyChanged)));
        
        #endregion        

        #region LaneIndex

        /// <summary>
        /// 车道索引
        /// </summary>
        public double LaneIndex
        {
            get { return (double)GetValue(LaneIndexProperty); }
            set { SetValue(LaneIndexProperty, value); }
        }

        public static readonly DependencyProperty LaneIndexProperty =
            DependencyProperty.Register("LaneIndex", typeof(double), typeof(Lane), new UIPropertyMetadata(0.0, new PropertyChangedCallback(PropertyChanged)));

        #endregion        
        
        #region Offset

        public double Offset
        {
            get { return (double)GetValue(OffsetProperty); }
            set { SetValue(OffsetProperty, value); }
        }

        // Using a DependencyProperty as the backing store for Offset.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty OffsetProperty =
            DependencyProperty.Register("Offset", typeof(double), typeof(Lane), new UIPropertyMetadata(0.0, new PropertyChangedCallback(PropertyChanged)));
        
        #endregion
        
        #region LaneDirectImage

        public string LaneDirectImage
        {
            get { return (string)GetValue(LaneDirectImageProperty); }
            set { SetValue(LaneDirectImageProperty, value); }
        }

        public static readonly DependencyProperty LaneDirectImageProperty =
            DependencyProperty.Register("LaneDirectImage", typeof(string), typeof(Lane), new PropertyMetadata(new PropertyChangedCallback(LaneDirectImagePropertyChanged)));

        private static void LaneDirectImagePropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            Lane lane = (Lane)d;
            if (lane != null && lane.LaneDirectImage != null)
            {
               // lane.DramLaneDirectImage();
            }
        }
        
        #endregion

        #region IsChecked

        public bool IsChecked
        {
            get { return (bool)GetValue(IsCheckedProperty); }
            set { SetValue(IsCheckedProperty, value); }
        }

        public static readonly DependencyProperty IsCheckedProperty =
            DependencyProperty.Register("IsChecked", typeof(bool), typeof(Lane), new UIPropertyMetadata(false));
  
        #endregion

        #endregion

        #region 注册事件

        #region Event
        private static readonly RoutedEvent CheckedEvent = EventManager.RegisterRoutedEvent(
             "Checked",
             RoutingStrategy.Bubble,
             typeof(RoutedEventHandler), typeof(Lane));

        public event RoutedEventHandler Checked
        {
            add { AddHandler(CheckedEvent, value); }
            remove { RemoveHandler(CheckedEvent, value); }
        }
        #endregion

        #region Event
        private static readonly RoutedEvent UnCheckedEvent = EventManager.RegisterRoutedEvent(
             "UnChecked",
             RoutingStrategy.Bubble,
             typeof(RoutedEventHandler), typeof(Lane));

        public event RoutedEventHandler UnChecked
        {
            add { AddHandler(UnCheckedEvent, value); }
            remove { RemoveHandler(UnCheckedEvent, value); }
        }
        #endregion

        #endregion
 
        #region 更新道路

        void CalMiddleLinePoints()
        {
            if (OriginPoints != null && OriginPoints.Count >= 2)
            {
                if (LaneIndex < 0)
                {
                    MiddleLinePoints = new PointCollection(LineHelper.MakeParallelLine(OriginPoints.ToList(), LaneWidth * LaneIndex + LaneWidth / 2 + LaneIndex));
                    laneLine.Points = new PointCollection(LineHelper.MakeParallelLine(MiddleLinePoints.ToList(), LaneWidth / 2 + 1));
                }
                else
                {
                    MiddleLinePoints = new PointCollection(LineHelper.MakeParallelLine(OriginPoints.ToList(), LaneWidth * LaneIndex - LaneWidth / 2 + LaneIndex));
                    laneLine.Points = new PointCollection(LineHelper.MakeParallelLine(MiddleLinePoints.ToList(), -LaneWidth / 2 - 1));
                }
            }
        }

        void PointsList_CollectionChanged()
        {
            if (MiddleLinePoints != null && MiddleLinePoints.Count >= 2)
            {
                polygon.Points = Helper.ConcatReversePoints(new PointCollection(LineHelper.MakeParallelLine(MiddleLinePoints.ToList(), LaneWidth / 2)), new PointCollection(LineHelper.MakeParallelLine(MiddleLinePoints.ToList(), -LaneWidth / 2)));             
            }
        }

        //void DramLaneDirectImage()
        //{
        //    LaneDirectImagepanel.Children.Clear();
        //    BitmapImage bi = new BitmapImage();
        //    bi.BeginInit();
        //    bi.UriSource = new Uri(LaneDirectImage, UriKind.RelativeOrAbsolute);
        //    bi.EndInit();
        //    PointCollection axlePoints = new PointCollection();
        //    for (int i = 0; i < PointsList[0].Count;i++ )
        //    {
        //        axlePoints.Add(new Point((PointsList[0][i].X + PointsList[1][i].X) / 2, (PointsList[0][i].Y + PointsList[1][i].Y) / 2));
        //    }
        //    double width = new Vector(PointsList[1][0].X-PointsList[0][0].X,PointsList[1][0].Y-PointsList[0][0].Y).Length;
        //    for (int i = 0; i < axlePoints.Count - 1;i++ )
        //    {
        //        if (i != axlePoints.Count - 1)
        //        {
        //            Vector small = new Vector(axlePoints[i + 1].X - axlePoints[i].X, axlePoints[i + 1].Y - axlePoints[i].Y);
        //            if (small.Length > bi.Height * 2)
        //            {
        //                Image img = new Image();
        //                img.Source = bi;
        //                TransformGroup tg = new TransformGroup();
        //                if (bi.Width > width)
        //                {
        //                    double delta = bi.Width / bi.Height;
        //                    tg.Children.Add(new ScaleTransform() { ScaleX = (width) / bi.Width, ScaleY = (width ) / bi.Width });
        //                }
        //                img.Opacity = 0.7;
        //                Canvas.SetLeft(img, axlePoints[i].X+ 0.5* small.X-0.5*bi.Width);
        //                Canvas.SetTop(img, axlePoints[i].Y + 0.5 * small.Y - 0.5 * bi.Height);
        //                img.RenderTransformOrigin = new Point(0.5, 0.5);
        //                tg.Children.Add(new RotateTransform()
        //                {
        //                    Angle =180- Vector.AngleBetween(new Vector(axlePoints[i + 1].X - axlePoints[i].X, axlePoints[i + 1].Y - axlePoints[i].Y), new Vector(0, 1))
        //                });
        //                img.RenderTransform = tg;
        //                LaneDirectImagepanel.Children.Add(img);
        //            }
        //        }
        //    }
        //}
        #endregion

        #region 道路状态

        private void status_MouseDown(object sender, MouseButtonEventArgs e)
        {
            if (IsChecked)
            {
                IsChecked = false;
                RaiseEvent(new RoutedEventArgs(UnCheckedEvent,false));
            }
            else
            {
                IsChecked = true;
                RaiseEvent(new RoutedEventArgs(CheckedEvent, true));
            }
        }
        
        #endregion       
    }
}
